package com.jg.xmlSchema2JsonSchema;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.XML;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.*;

import java.awt.*;
import java.io.File;
import java.io.IOException;

/**
 * @author czg
 */
public class Xml2JsonApp {

    protected Shell shell;
    private Button btnXmlSchema2JsonSchema;
    private Button btnXml2Json;
    private Composite compositeSelect2Type;
    private Composite compositeOperate;
    private Button btnDelete;
    private Button btnClear;
    private Button btnRun;
    private int toType = 0;
    private Table table;

    private final static String SOURCE_KEY = "source";
    private Button buttonOverride;
    private Button buttonSkip;
    private Button buttonAutoName;

    /**
     * Launch the application.
     *
     * @param args
     */
    public static void main(String[] args) {
        try {
            Xml2JsonApp window = new Xml2JsonApp();
            window.open();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Open the window.
     */
    public void open() {
        Display display = Display.getDefault();
        createContents();
        shell.open();
        shell.layout();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
    }

    /**
     * Create contents of the window.
     */
    protected void createContents() {
        shell = new Shell(SWT.BORDER | SWT.CLOSE);
        shell.addShellListener(new ShellAdapter() {
            @Override
            public void shellActivated(ShellEvent e) {
                updateButtonState();
            }
        });
        shell.setSize(1071, 570);
        shell.setText("Xml To Json");

        Button btnClose = new Button(shell, SWT.NONE);
        btnClose.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                shell.dispose();
            }
        });
        btnClose.setBounds(965, 496, 80, 27);
        btnClose.setText("关闭");

        compositeOperate = new Composite(shell, SWT.NONE);
        compositeOperate.setBounds(10, 43, 1035, 27);

        Button btnAdd = new Button(compositeOperate, SWT.NONE);
        btnAdd.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                addXmlFile();
            }
        });
        btnAdd.setBounds(0, 0, 164, 27);
        btnAdd.setText("添加需要转换的xml文件");

        btnDelete = new Button(compositeOperate, SWT.NONE);
        btnDelete.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                deleteSelect();
            }
        });
        btnDelete.setBounds(170, 0, 80, 27);
        btnDelete.setText("删除");

        btnClear = new Button(compositeOperate, SWT.NONE);
        btnClear.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                clearList();
            }
        });
        btnClear.setBounds(256, 0, 80, 27);
        btnClear.setText("清除");


        btnRun = new Button(compositeOperate, SWT.NONE);
        btnRun.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                try {
                    doToJson();
                } catch (IOException ex) {
                    ex.printStackTrace();
                    MessageDialog.openError(shell, "错误", StrUtil.format("转换失败:{}", ex.getMessage()));
                }
            }
        });
        btnRun.setBounds(955, 0, 80, 27);
        btnRun.setText("开始转换");

        Label label = new Label(compositeOperate, SWT.NONE);
        label.setBounds(658, 5, 91, 17);
        label.setText("文件存在选择：");

        buttonOverride = new Button(compositeOperate, SWT.RADIO);
        buttonOverride.setSelection(true);
        buttonOverride.setBounds(755, 5, 53, 17);
        buttonOverride.setText("覆盖");

        buttonSkip = new Button(compositeOperate, SWT.RADIO);
        buttonSkip.setText("跳过");
        buttonSkip.setBounds(814, 5, 53, 17);

        buttonAutoName = new Button(compositeOperate, SWT.RADIO);
        buttonAutoName.setText("自动命名");
        buttonAutoName.setBounds(873, 5, 74, 17);


        compositeSelect2Type = new Composite(shell, SWT.NONE);
        compositeSelect2Type.setBounds(10, 10, 661, 27);

        btnXmlSchema2JsonSchema = new Button(compositeSelect2Type, SWT.RADIO);
        btnXmlSchema2JsonSchema.setSelection(true);
        btnXmlSchema2JsonSchema.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                typeSelect();
            }
        });
        btnXmlSchema2JsonSchema.setBounds(3, 6, 171, 17);
        btnXmlSchema2JsonSchema.setText("XmlSchema转JsonSchema");

        btnXml2Json = new Button(compositeSelect2Type, SWT.RADIO);
        btnXml2Json.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                typeSelect();
            }
        });
        btnXml2Json.setText("Xml转Json");
        btnXml2Json.setBounds(207, 6, 97, 17);

        table = new Table(shell, SWT.BORDER | SWT.FULL_SELECTION);
        table.setBounds(10, 73, 1035, 409);
        table.setHeaderVisible(true);
        table.setLinesVisible(true);

        TableColumn tableColumn = new TableColumn(table, SWT.NONE);
        tableColumn.setWidth(855);
        tableColumn.setText("文件");

        TableColumn tblclmnNewColumn = new TableColumn(table, SWT.NONE);
        tblclmnNewColumn.setWidth(163);
        tblclmnNewColumn.setText("转换结果");

    }

    protected void typeSelect() {
        // TODO Auto-generated method stub
        if (btnXmlSchema2JsonSchema.getSelection()) {
            if (toType == 2 && table.getItemCount() > 0) {
                if (MessageDialog.openConfirm(shell, "选择", "转换类型发生变化，是否清除已选择的文件？")) {
                    table.removeAll();
                } else {
                    btnXml2Json.setSelection(true);
                    return;
                }
            }
            toType = 1;
        } else if (btnXml2Json.getSelection()) {
            if (toType == 2 && table.getItemCount() > 0) {
                if (MessageDialog.openConfirm(shell, "选择", "转换类型发生变化，是否清除已选择的文件？")) {
                    table.removeAll();
                } else {
                    btnXmlSchema2JsonSchema.setSelection(true);
                    return;
                }
            }
            toType = 2;
        }
    }

    private void doToJson() throws IOException {
        String outDir = getPath(shell, null, "数据库实体类在工程里存放根目录");
        if (outDir == null) {
            return;
        }
        compositeSelect2Type.setEnabled(false);
        compositeOperate.setEnabled(false);
        table.setEnabled(false);
        // TODO Auto-generated method stub
        for (TableItem item : table.getItems()) {
            String file = (String) item.getData(SOURCE_KEY);
            System.out.println(file);
            String covertResult = null;
            try {
                covertResult = covertToJson(outDir, file);
            } catch (Exception e) {
                e.printStackTrace();
                MessageDialog.openError(shell, "错误", StrUtil.format("转换失败:{}", e.getMessage()));
                covertResult = "失败";
            }
            item.setText(1, covertResult);
        }
        compositeSelect2Type.setEnabled(true);
        compositeOperate.setEnabled(true);
        table.setEnabled(true);
        Desktop.getDesktop().open(new File(outDir));
    }

    private String covertToJson(String outDir, String file) throws Exception {
        System.out.println(file);
        File xmlFile = new File(file);
        String jsonFileMainName = FileNameUtil.mainName(xmlFile);
        String jsonSchemaFileName = StrUtil.format("{}{}{}.json", outDir, File.separator, jsonFileMainName);
        if (new File(jsonSchemaFileName).exists()) {
            buttonOverride.getSelection();
            if (buttonSkip.getSelection()) {
                return "跳过";
            }
            if (buttonAutoName.getSelection()) {
                jsonSchemaFileName = getLastFileName(outDir, jsonFileMainName);
            }
        }
        if (btnXmlSchema2JsonSchema.getSelection()) {
            XsdFileToJsonSchema xsdFileToTemplate = new XsdFileToJsonSchema(xmlFile);
            xsdFileToTemplate.save(jsonSchemaFileName);
        }
        if (btnXml2Json.getSelection()) {
            String xmlContent = FileUtil.readString(xmlFile, CharsetUtil.UTF_8);
            cn.hutool.json.JSONObject jsonObject = XML.toJSONObject(xmlContent);
            jsonObject.toJSONString(3);
            FileUtil.writeString(jsonObject.toJSONString(3), jsonSchemaFileName, CharsetUtil.UTF_8);
        }
        return "成功";
    }

    private String getLastFileName(String outDir, String fileMainName) {
        return getLastFileName(outDir, fileMainName, null);
    }

    private String getLastFileName(String outDir, String fileMainName, Integer index) {
        String jsonSchemaFileName;
        if (index == null) {
            jsonSchemaFileName = StrUtil.format("{}{}{}.json", outDir, File.separator, fileMainName);
        } else {
            jsonSchemaFileName = StrUtil.format("{}{}{}{}.json", outDir, File.separator, fileMainName, index);
        }
        if (!FileUtil.exist(jsonSchemaFileName)) {
            return jsonSchemaFileName;
        }
        return getLastFileName(outDir, fileMainName, index == null ? 1 : index + 1);
    }


    private void deleteSelect() {
        // TODO Auto-generated method stub
        for (int i = table.getSelectionIndices().length - 1; i >= 0; i--) {
            table.remove(i);
        }
        updateButtonState();
    }

    private void addXmlFile() {
        // TODO Auto-generated method stub
        String[] filterExtensions;
        String[] filterNames;
        String message;
        if (btnXmlSchema2JsonSchema.getSelection()) {
            filterExtensions = new String[]{"*.xsd", "*.xml", "*.*"};
            filterNames = new String[]{"xml schema 文件(*.xsd)", "xml 文件(*.xml)", "全部文件(*.*)"};
            message = "选择xml schema文件";
        } else if (btnXml2Json.getSelection()) {
            filterExtensions = new String[]{"*.xml", "*.*"};
            filterNames = new String[]{"xml 文件(*.xml)", "全部文件(*.*)"};
            message = "选择xml文件";
        } else {
            return;
        }
        String[] files = getFile(shell, null, message, filterExtensions, filterNames);
        if (files == null) {
            return;
        }
        for (String file : files) {
            if (!exist(file)) {
                TableItem tableItem = new TableItem(table, SWT.NONE);    //每循环一次，就新建一行
                tableItem.setText(new String[]{file, ""});
                tableItem.setData(SOURCE_KEY, file);
            }
        }
        updateButtonState();
    }

    private boolean exist(String file) {
        for (int i = 0; i < table.getItemCount(); i++) {
            if (table.getItem(i).getData(SOURCE_KEY).equals(file)) {
                return true;
            }
        }
        return false;
    }

    private void clearList() {
        // TODO Auto-generated method stub
        table.removeAll();
        updateButtonState();
    }

    /**
     * 用目录选择对话框获得所选目录
     *
     * @param shell
     * @param rootPath
     * @param message
     * @return
     */
    public String getPath(Shell shell, String rootPath, String message) {
        DirectoryDialog dd = new DirectoryDialog(shell);
        dd.setMessage(message);
        dd.setText("选择文件夹");
        dd.setFilterPath(rootPath);
        return dd.open();
    }

    /**
     * @param shell
     * @param rootPath
     * @param message
     * @param filterExtensions 如new String[]{"*.txt","*.*"}
     * @param filterNames      如new String[]{"Text Files(*.txt)","All Files(*.*)"}
     * @return
     */
    public String[] getFile(Shell shell, String rootPath, String message, String[] filterExtensions, String[] filterNames) {
        FileDialog fd = new FileDialog(shell, SWT.MULTI);
        fd.setFilterPath(rootPath);
        if (filterExtensions != null) {
            fd.setFilterExtensions(filterExtensions);
        }
        if (filterNames != null) {
            fd.setFilterNames(filterNames);
        }
        fd.open();
        String[] selected = fd.getFileNames();
        if (selected.length == 0) {
            return null;
        }
        String path = fd.getFilterPath();
        for (int i = 0; i < selected.length; i++) {
            selected[i] = path + File.separator + selected[i];
        }
        return selected;
    }

    private void updateButtonState() {
        btnDelete.setEnabled(table.getSelectionCount() > 0);
        btnClear.setEnabled(table.getItemCount() > 0);
        btnRun.setEnabled(table.getItemCount() > 0);
    }
}
